#!/usr/bin/env python
#
# Copyright 2008 Richard J. Bell. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

""" Geo handlers for geo wiki (great-loop) site. """

# Python Imports

# Google App Engine Imports
from google.appengine.ext import webapp

# Application Imports

class GeoRequest(webapp.RequestHandler):
    # todo: this should probably come from BaseRequestHandler
    """ Handles all requests to /gen/request """
    def post(self):
        self.operationPicker()

    def get(self):
        self.operationPicker()

    def operationPicker(self):
        operation = self.request.get('operation')
        out,contentType = '',''
        if operation == 'add':
            out,contentType = self.addGeometries()
        elif operation == 'edit':
            out,contentType = self.editGeometries()
        elif operation == 'delete':
            out,contentType = self.deleteGeometries()
        else:
            out,contentType = self.getGeometries()
        self.response.headers['Content-Type'] = contentType
        self.response.out.write(out)

    def getGeometries(self):
        limit = self.request.get('limit',default_value=10)
        output = self.request.get('output',default_value='json')
        userid = self.request.get('userid',default_value=None)

        query = []
        type = self.request.get('type',default_value=None)
        distance = self.request.get('distance',default_value=None)
        bbox = self.request.get('BBOX', default_value=None)
        qryString = ''
        argsString = ''
        if type: 
            query.append("type = '%s'" % type)
        if userid: 
            query.append("userId = '%s'" % userid)

        bboxWest = None
        bboxSouth = None
        bboxEast = None
        bboxNorth = None

        if bbox:
            bboxList = bbox.split(',')
            bboxWest = float(bboxList[0])
            bboxSouth = float(bboxList[1])
            bboxEast = float(bboxList[2])
            bboxNorth = float(bboxList[3])
        queryString = '' 
        if len(query) > 0:
            queryString = 'WHERE %s LIMIT %s' % (' and '.join(query), limit)

        if (output == 'georss'):
            geometriesPickled  = memcache.get(MEMCACHE_GEOMETRYBYDATE)
            if geometriesPickled is None:
                query = Geometry.all()
                query.order('-dateModified')
                geometries = query.fetch(limit=20)
                if not memcache.set(MEMCACHE_GEOMETRYBYDATE, pickle.dumps(geometries)):
                    logging.debug('Memcache set failed')
            else:
                geometries = pickle.loads(geometriesPickled)
        elif (len(query) == 0):
            geometriesPickled  = memcache.get(MEMCACHE_GEOMETRYALL)
            if geometriesPickled is None:
                query = Geometry.all()
                geometries = query.fetch(limit=limit)
                if not memcache.set(MEMCACHE_GEOMETRYALL, pickle.dumps(geometries)):
                    logging.debug('Memcache set failed')
            else:
                geometries = pickle.loads(geometriesPickled)
        else: 
            geometries = Geometry.gql(queryString)

        outputAction = {'json': jsonOutput(geometries,'get'),
                        'kml': kmlOutput(geometries,bboxWest,bboxSouth,bboxEast,bboxNorth),
                        'georss': georssOutput(geometries)}
        out,contentType = outputAction.get(output)
        return out,contentType

    def addGeometries(self):
        try:
            lat = self.request.get('lat',allow_multiple=True,default_value=0.0)
            lng = self.request.get('lng',allow_multiple=True,default_value=0.0)
            name = self.request.get('name',default_value = '')
            alts = self.request.get('alt', allow_multiple=True, default_value=0.0)
            tags = self.request.get('tag', allow_multiple=True, default_value=None)
            user = users.GetCurrentUser()
            userid=None
            if user:
                userid=user.email()
            west, south, east, north = computeBBox(lat,lng)
            coords = []
            for i in range(0, len(lat)):
                gp = db.GeoPt(lat[i], lng[i])
                coords.append(gp)
            altitudes = []
            for alt in alts:
                altitudes.append(float(alt))
            description = self.request.get('description')
            type = self.request.get('type',default_value='point')
            hash = None
            if type == 'point':
                hash = str(geohash.Geohash((float(lat[0]), float(lng[0]))))
            gp = Geometry(name=name, description=description, type=type,
                          coordinates=coords, altitudes=altitudes,
                          tags=tags, bboxEast=east, bboxWest=west,
                          bboxSouth=south, bboxNorth=north, userId=userid,
                          geohash=hash)

            gp.put()
            gps = []
            gps.append(gp)
            clearMemcache();
            jsonResponse,contentType = jsonOutput(gps,'add')

        except TypeError, ValueError:
            jsonResponse="{error:{type:'add',lat:'%s',lng:'%s'}}" % (lat[0], lng[0])
            contentType = 'text/javascript'
        return jsonResponse,contentType

    def editGeometries(self):
        try:
            lat = self.request.get('lat',allow_multiple=True,default_value=0.0)
            lng = self.request.get('lng',allow_multiple=True,default_value=0.0)
            name = self.request.get('name',default_value = '')
            alts = self.request.get('alt', allow_multiple=True, default_value=0.0)
            tags = self.request.get('tag', allow_multiple=True, default_value=None) 
            key = self.request.get('key')
            west, south, east, north = computeBBox(lat,lng)
            coords = []
            for i in range(0, len(lat)):
                gp = db.GeoPt(lat[i], lng[i])
                coords.append(gp)

            description = self.request.get('description')
            type = self.request.get('type',default_value='point')

            gp = Geometry.get(key)
            gp.name = name
            gp.description=description
            gp.type=type
            gp.coordinates=coords
            gp.altitudes=alts
            gp.tags=tags
            gp.bboxEast=east
            gp.bboxWest=west
            gp.bboxSouth=south
            gp.bboxNorth=north
            gp.put()
            gps = [gp]
            gps.append(gp)
            clearMemcache();
            jsonResponse,contentType = jsonOutput(gps, 'edit')

        except TypeError, ValueError:
            jsonResponse="{error:{type:'edit',key:'%s'}}" % self.request.get('key')
            contentType = 'text/javascript'
        return jsonResponse,contentType


    def deleteGeometries(self):
        success = "success"

        try:
            key = str(self.request.get('key'))
            gp = Geometry.get(key)
            gp.delete()
            jsonResponse = "{operation:'delete',status:'success',key:'%s'}" % key
        except:
            jsonResponse = "{error:{type:'delete',records:{key:'%s'}}}" % self.request.get('key')
        contentType = 'text/javascript'
        clearMemcache();
        return jsonResponse,contentType
